
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.StringTokenizer;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class LeerXML {
	public static void main(String args[]) {
		
		
		if ( args.length != 2) {
		System.err.println("Uso: java LeerXMl archivo.xml (contar||procesar||bitacora)");
		System.exit(-1);
		}
		final String archivo = args[0];
		final String operacion = args[1];
		try {
									
			SAXParserFactory factory = SAXParserFactory.newInstance();
			SAXParser saxParser = factory.newSAXParser();
			
			DefaultHandler handler = new DefaultHandler() {
			
			StringBuffer Contenido = new StringBuffer();
			StringBuffer lineaFinal = new StringBuffer();
			StringBuffer Iniciales = new StringBuffer();
			StringBuffer Finales = new StringBuffer();
			StringBuffer ISMPP = new StringBuffer();
			String PortType = "";
			String Action = "";
			int rangos = 0;
			int procesos = 0;
			int numeros = 0;
			Long numero;
			Long nInicial;
			Long nFinal;
			String iniciales = "";
			String finales = "";
			String ismpp = "";
			String isRng = "";
			String isMpp = "";
			String Donor = "";
			String Assignee = "";
			String datos = "";
			String Recipient = "";
			String fEjec = "";
			String fArch = "";
			StringTokenizer NumberFrom;
			StringTokenizer NumberTo;
			StringTokenizer isMPP;
									
			public void startElement(String uri, String localName,
					String qName, Attributes attibutes)
			        throws SAXException {
				Contenido.setLength(0);
				if (qName.equalsIgnoreCase("PortData")) {
					Iniciales.setLength(0);
					Finales.setLength(0);
					ISMPP.setLength(0);					
				}
			}
			public void characters(char ch[], int start, int length)
			         throws SAXException {
				try {
					String texto = new String(ch, start, length);
					Contenido = Contenido.append(texto);
					datos = Contenido.toString();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			public void endElement(String uri, String localName, String qName)  
			         throws SAXException {
				if (qName.equalsIgnoreCase("Timestamp")) {
					fArch = datos;
				}
				if (qName.equalsIgnoreCase("PortType")) {
					PortType = datos;
				}
				if (qName.equalsIgnoreCase("Action")) {
					Action = datos;
				}
				if (qName.equalsIgnoreCase("NumberFrom")) {
					Iniciales.append(datos + "|");
				}
				if (qName.equalsIgnoreCase("NumberTo")) {
					Finales.append(datos + "|");
				}
				if (qName.equalsIgnoreCase("isMPP")) {
					ISMPP.append(datos + "|");
				}
				if (qName.equalsIgnoreCase("NumberRange")) {
					iniciales = Iniciales.toString();
					finales = Finales.toString();
					ismpp = ISMPP.toString();
					NumberFrom = new StringTokenizer(iniciales, "|");
					NumberTo = new StringTokenizer(finales, "|");
					isMPP = new StringTokenizer(ismpp, "|");
					rangos ++;
				}
				if (qName.equalsIgnoreCase("Donor")) {
					if (Action.equalsIgnoreCase("Reverse")) {
						Recipient = datos;
					}else {
						Donor = datos;
					}
				}
				if (qName.equalsIgnoreCase("Assignee")) {
					Assignee = datos;
					if (Donor.equalsIgnoreCase("")) {
						Donor = Assignee;
					}
				}
				if (qName.equalsIgnoreCase("Recipient")) {
					if (Action.equalsIgnoreCase("Reverse")) {
						Donor = datos;
					}else {
						Recipient = datos;
					}
				}
				if (qName.equalsIgnoreCase("ActionDate")) {
					fEjec = datos;
				}
				if (qName.equalsIgnoreCase("PortData")) {
					procesos ++;
					
					while (NumberFrom.hasMoreTokens()) {
						
						isMpp = isMPP.nextToken();
						nInicial = Long.parseLong(NumberFrom.nextToken());
						nFinal = Long.parseLong(NumberTo.nextToken());
						if (nInicial < nFinal) {
							isRng = "Y";
						}
						else {
							isRng = "N";
						}
						for (numero = nInicial;numero <= nFinal;numero ++) {
							numeros++;

							String linea = numero + "|" + 
									       numeros + "|" +
									       nInicial + "|" +
									       nFinal + "|" +
									       Donor + "|" +
									       Recipient + "|" +
									       isRng + "|" +
									       isMpp + "|" +
									       fArch + "|" +
									       fEjec + "|" +
									       PortType + "|" +
									       Action + "|" +
									       "Daily\n";
							lineaFinal.append(linea);
						}
					}				
				}
				//Solo se muestra el conteo del contenido
				if (qName.equalsIgnoreCase("NPCData")) {
					if (operacion.equalsIgnoreCase("contar")) {
						System.out.println(fecha() + " Archivo analizado: " + archivo);
						System.out.println(fecha() + " Contiene:");
						System.out.println(fecha() + " " + procesos + "\tprocesos.");
						System.out.println(fecha() + " " + rangos + "\trangos.");
						System.out.println(fecha() + " " + numeros + "\tlineas.");
					}
					if (operacion.equalsIgnoreCase("bitacora")) {
						String tarch = "";
						if (archivo.substring(7,13).equalsIgnoreCase("Ported")) {
							tarch = "PORTADOS";
						} else {
							tarch = "BORRADOS";
						}
						System.out.println(archivo +"|" + procesos + "|" + rangos +
								"|" + numeros + "|" + tarch + "|" +  fArch);
					}
					if (operacion.equalsIgnoreCase("procesar")) {
						System.out.println(lineaFinal.toString());	
					}
				}
			}			
		};
		
		saxParser.parse(args[0], handler);
		
	} catch (Exception e) {
		e.printStackTrace();
		}
	}

	public static String fecha () {
		String fech = "";
		SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
		
		Calendar cal1 = Calendar.getInstance();
	    fech = df.format(cal1.getTime());
	    return fech;
	}
}